import 'package:flutter/material.dart';

/// 2023-4-8
class Demo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("1. 溢出问题", style: TextStyle(fontSize: 20)),
          Text("文本其实不会溢出，默认会自动换行 !" * 3),
          SizedBox(height: 10),
          Row(children: [
            Text("被Row包裹了，非要显示在一行内，才不会换行 ! 那自然就会有矛盾点了：溢出问题  " * 2)
          ]),
          Text("矛盾点：如果超过一行，是省略..., 还是截断，还是换行，还是文字缩小？其实给个默认值更好吧，不要这么直接报错了"),
          SizedBox(height: 10),
          Wrap(children: [Text("被wrap包裹, 又能解决这个问题，自动换行 !  " * 3)]),
          SizedBox(height: 30),
          Text("2. 需要解决的溢出需求点 ≈? 自适应", style: TextStyle(fontSize: 20)),
          Text("同样的宽高"),
          Text("a. 子组件原始大小超过了父组件的约束区域: 子组件进行缩小、裁剪或者换行；"),
          Text('b. 子组件原始大小小于父组件的越苏区域：子组件不变、始终居中、填充父组件'),
          Text("自适应不同的父组件宽高，即适应不同的手机屏幕"),
          SizedBox(height: 30),
          Text("3. FittedBox, 请开始你的表演：", style: TextStyle(fontSize: 20)),
          Text("3.1 解决溢出问题"),
          Text('子组件默认展示本身大小。子组件大于父组件，溢出了，所以这里叠加了'),
          wContainer(BoxFit.none),
          SizedBox(height: 10),
          Text('方法1：上一课学习的ClipRRect, 可以对溢出的子组件进行裁剪, 避免文字叠加'),
          ClipRRect(child: wContainer(BoxFit.none)),
          Text('方法2：BoxFit.contain: 子组件缩小，适配父组件.'),
          wContainer(BoxFit.contain),

          SizedBox(height: 10),
          Text("3.2 FittedBox来做自适应："),
          SizedBox(height: 10),
          Text("长度太长了会溢出的"),
          wRow(' 9000000000000000000000000 '),
          Text("FitttdBox默认缩小 fit = BoxFit.contain"),
          FittedBox(child: wRow(' 9000000000000000000000000 ')),
          Text("数字长度小的时候，原始还能很好显示"),
          wRow(' 900 '),
          Text("but, FittedBox设计的不好，当数字没那么大时，应用FittedBox，会挤压在一起"),
          FittedBox(child: wRow(' 900 ')),
          // 在FittedBox和Row中间隔上一个BoxConstraints
          LayoutBuilder(builder: (_, constraints) {
            return FittedBox(
                child: ConstrainedBox(
              constraints: BoxConstraints(
                // 传递屏幕的宽度
                maxWidth: constraints.maxWidth,
              ),
              child: wRow(' 900 '),
            ));
          }),
          Text("作者封装的单行自适应组件"),
          SingleLineFittedBox(child: wRow(' 9000000000000000000000000 ')),
          SingleLineFittedBox(child: wRow(' 900 ')),
          SizedBox(height: 50),
          Text("4. 原理总结：", style: TextStyle(fontSize: 20)),
          Text(
              '1. 父组件没有约束时，子组件默认展示自己的大小，父组件随着撑大; 父组件有大小 & > 子组件，子组件进行原样显示; 父组件有大小 & < 子组件, 子组件缩小或裁剪'),
          Text('2. FittedBox相当于再父子中间插入了一个隔阂，即知道父组件约束，也知道子组件大小'),
          Text(
              "3.1 Boxfit.none: 忽略父组件传递下来的约束，因为它往子组件传递：0<=width<=double.infinity, 0<= height <=double.infinity， 相当于让子组件尽情左自己'"),
          Text("3.2 Boxfit.contain: 往左子组件传递父组件约束"),
          Text(
              "4. 可以缩小字体，不溢出的单行自适应, 这也太复杂了吧：FittedBox(ConstrainedBox(minWidth: 屏幕宽度，child: Row(MainAxisAlignment.spaceEvenly, xxx)))")
        ],
      ),
    );
  }
}

Widget wContainer(BoxFit boxFit) {
  return Container(
    width: 50,
    height: 50,
    color: Colors.red,
    child: FittedBox(
      fit: boxFit,
      // 子容器超过父容器大小
      child: Container(width: 60, height: 70, color: Colors.blue),
    ),
  );
}

Widget wRow(String text) {
  Widget child = Text(text);
  child = Row(
    // 一定需要父组件传递限制下来，默认传下来的父组件宽度是屏幕宽度
    // 如果用FitedBox包裹，传递下来的maxWidth就是double.infinity, 此时就无法计算啦，so spaceEvenly会失效
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [child, child, child],
  );
  return child;
}

// https://book.flutterchina.club/chapter5/fittedbox.html#_5-6-2-%E5%AE%9E%E4%BE%8B-%E5%8D%95%E8%A1%8C%E7%BC%A9%E6%94%BE%E5%B8%83%E5%B1%80
// 作者封装的单行自适应组件：
// 父空间不够，子自动缩小； 父空间很大，子自动扩大填充
class SingleLineFittedBox extends StatelessWidget {
  const SingleLineFittedBox({Key? key, this.child}) : super(key: key);
  final Widget? child;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (_, constraints) {
        return FittedBox(
          child: ConstrainedBox(
            // 将最小宽度（minWidth）约束指定为屏幕宽度，因为Row必须得遵守父组件的约束，所以 Row 的宽度至少等于屏幕宽度，所以就不会出现缩在一起的情况；
            // maxWidth 指定为无限大，则就可以处理数字总长度超出屏幕宽度的情况。
            constraints: constraints.copyWith(
              minWidth: constraints.maxWidth,
              maxWidth: double.infinity,
              //maxWidth: constraints.maxWidth
            ),
            child: child,
          ),
        );
      },
    );
  }
}

void main(List<String> args) {
  runApp(MaterialApp(
    home: Scaffold(body: Demo()),
  ));
}
